home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / video / fly8111-.000 / fly8111- / fly8 / COMMON / timer.c < prev    next >
C/C++ Source or Header  |  1979-12-31  |  4KB  |  198 lines

  1. /* --------------------------------- timer.c -------------------------------- */
  2.  
  3. /* This is part of the flight simulator 'fly8'.
  4.  * Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au).
  5. */
  6.  
  7. /* High resolution time services directly reading the 8254.
  8. */
  9.  
  10. #include "fly.h"
  11. #include "pc8254.h"
  12.  
  13. #include <time.h>
  14.  
  15. #ifdef DJGPP
  16. #include <pc.h>
  17.  
  18. #define inp(p)         inportb(p)
  19. #define outp(p,b)    outportb(p,b)
  20. #else
  21. #include <conio.h>
  22. #endif
  23.  
  24.  
  25. static Ushort    counter = 0;
  26. static Ulong    seconds = 0, ticks = 0;
  27. static Ulong    timer_period = TIMER_PERIOD;
  28.  
  29. LOCAL_FUNC int FAR
  30. TmrHires (void)        /* get fastest timer available */
  31. {
  32.     Ushort        t, status;
  33.     Ulong        flags;
  34.  
  35.     do {
  36.         flags = Sys->Disable ();
  37.         outp (COMMAND_REG, READ_SPECIAL);
  38.         iefbr14 ();                /* delay */
  39.         status = (Ushort) inp (CHANNEL_0);    /* get status */
  40.         iefbr14 ();                /* delay */
  41.         t  = (Ushort)inp (CHANNEL_0);        /* low byte */
  42.         iefbr14 ();                /* delay */
  43.         t += (Ushort)(inp (CHANNEL_0) << 8);    /* high byte */
  44.         Sys->Enable (flags);
  45.     } while (0 == t);
  46.  
  47.     if ((status & TIMER_MODES) == TIMER_MODE*3) {
  48.         t >>= 1;
  49.         if (status & TIMER_OUT)
  50.             t += (Ushort)((timer_period+1)/2);
  51.     }
  52.     t = (Ushort)(timer_period - t);        /* make it count up */
  53.     return ((int)t);
  54. }
  55.  
  56. LOCAL_FUNC void NEAR
  57. TmrGet (void)
  58. {
  59.     Ushort        t;
  60.  
  61.     t = (Ushort) TmrHires ();
  62.  
  63.     if (t >= counter)
  64.         ticks += t - counter;
  65.     else
  66.         ticks += (t+timer_period) - counter;
  67.     counter = t;
  68.     while (ticks >= XTAL) {
  69.         ticks -= XTAL;
  70.         ++seconds;
  71.     }
  72. }
  73.  
  74. LOCAL_FUNC Ulong FAR
  75. TmrMilli (void)
  76. {
  77.     TmrGet ();
  78.     return (seconds * 1000L + ticks * 1000L / XTAL);
  79. }
  80.  
  81. #define NINTS        10
  82.  
  83. LOCAL_FUNC Ulong FAR
  84. TmrInterval (int mode, Ulong res)
  85. {
  86.     static Ulong    last_seconds[NINTS], last_ticks[NINTS];
  87.     static int    n = -1;
  88.     Ulong        t = 0;
  89.  
  90.     if (mode & TMR_PUSH) {
  91.         ++n;
  92.         if (n >= NINTS) {
  93.             LogPrintf ("timer: too many PUSHes... aborting\n");
  94.             die ();
  95.         }
  96.     } else if (n < 0) {
  97.         LogPrintf ("timer: too many POPs... aborting\n");
  98.         die ();
  99.     }
  100.  
  101.     if (mode & (TMR_READ|TMR_SET))
  102.         TmrGet ();
  103.  
  104.     if (mode & TMR_READ) {
  105.         if (res > XTAL)
  106.             res = 0;
  107.         if (res > 0x7fffffffL/XTAL) {
  108.             Ulong    tt;
  109.  
  110.             tt = res/(0x7fffffffL/XTAL) + 1;
  111.             t = (seconds-last_seconds[n]) * res;
  112.             if (ticks > last_ticks[n])
  113.                 t += ((ticks-last_ticks[n]) * (res/tt))
  114.                     / (XTAL/tt);
  115.             else
  116.                 t -= ((last_ticks[n]-ticks) * (res/tt))
  117.                     / (XTAL/tt);
  118.         } else if (res)
  119.             t = (seconds-last_seconds[n]) * res
  120.                 + (long)((ticks-last_ticks[n]) * res) / XTAL;
  121.         else
  122.             t = (seconds-last_seconds[n]) * XTAL
  123.                 + (long)(ticks-last_ticks[n]);
  124.     }
  125.  
  126.     if (mode & TMR_SET) {
  127.         last_seconds[n] = seconds;
  128.         last_ticks[n]   = ticks;
  129.     }
  130.  
  131.     if (mode & TMR_POP)
  132.         --n;
  133.     return (t);
  134. }
  135.  
  136. LOCAL_FUNC int FAR
  137. TmrInit (char *options)
  138. {
  139.     int        status;
  140.     Ulong        flags;
  141.     long        l;
  142.  
  143.     if (options) {
  144.         if (!get_narg (options, "rate", &l)
  145.             && l > 0 && l <= 0x10000L)
  146.             timer_period = (Ulong)l;
  147.         else
  148.             timer_period = TIMER_PERIOD;
  149.         LogPrintf ("Timer period %ld\n", timer_period);
  150.     }
  151.     
  152.     flags = Sys->Disable ();
  153.     outp (COMMAND_REG, READ_SPECIAL);
  154.     iefbr14 ();
  155.     status = inp (CHANNEL_0);            /* get status */
  156.     (void)inp (CHANNEL_0);
  157.     (void)inp (CHANNEL_0);
  158.     Sys->Enable (flags);
  159.  
  160.     seconds = time (NULL);
  161.     counter = 0;
  162.     ticks = 0;
  163.  
  164.     status &= TIMER_MODES;
  165.     return (status != TIMER_MODE*2 && status != TIMER_MODE*3);
  166. }
  167. #undef NINTS
  168.  
  169. LOCAL_FUNC void FAR
  170. TmrTerm (void)
  171. {}
  172.  
  173. LOCAL_FUNC char * FAR
  174. TmrCtime (void)
  175. {
  176.     time_t    tm;
  177.     char    *t;
  178.     int    bug;
  179.  
  180.     tm = time (0);
  181.     t = ctime (&tm);
  182.     bug = strlen (t);    /* micro&soft hits again! */
  183.     t[bug - 1] = '\0';    /* kill NewLine */
  184.     return (t);
  185. }
  186.  
  187. struct TmDriver NEAR TmDriver = {
  188.     "PC8254",
  189.     0,
  190.     NULL,    /* extra */
  191.     TmrInit,
  192.     TmrTerm,
  193.     TmrMilli,
  194.     TmrHires,
  195.     TmrCtime,
  196.     TmrInterval
  197. };
  198.